﻿using AutoMapper;
using DFGK.IRepository;
using DFGK.IService;
using DFGK_WMS.Common;
using DFGK_WMS.Model.Dto;
using DFGK_WMS.Model.Enum;
using DFGK_WMS.Model.Models;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Yitter.IdGenerator;

namespace DFGK.Service
{
    public class ShippingReplenishmentService : BaseService, IShippingReplenishmentService
    {
        private readonly IShippingReplenishmentRepository _shippingReplenishmentRepository;
        private readonly IReceivingOrderDetailRepository _receivingOrderDetailRepository;
        private readonly IPickingOrderDetailRepository _pickingOrderDetailRepository;
        private readonly IShippingLockCellRepository _shippingLockCellRepository;
        private readonly IInventoryLogRepository _inventoryLogRepository;
        private readonly IPutawayOrderRepository _putawayOrderRepository;
        private readonly IPickingOrderRepository _pickingOrderRepository;
        private readonly IInventoryRepository _inventoryRepository;
        private readonly IInstructRepository _instructRepository;
        private readonly ICellRepository _cellRepository;
        private readonly WcsHttpClient _wcsHttpClient;
        private readonly IUnitOfWork _unitOfWork;
        public ShippingReplenishmentService(IMapper mapper, IShippingReplenishmentRepository _shippingReplenishmentRepository, IUnitOfWork _unitOfWork, IInventoryRepository _inventoryRepository, IInstructRepository _instructRepository, ICellRepository _cellRepository, IShippingLockCellRepository _shippingLockCellRepository, IInventoryLogRepository _inventoryLogRepository, IPickingOrderRepository _pickingOrderRepository, IPickingOrderDetailRepository _pickingOrderDetailRepository, WcsHttpClient _wcsHttpClient, IPutawayOrderRepository _putawayOrderRepository, IReceivingOrderDetailRepository _receivingOrderDetailRepository) : base(mapper)
        {
            this._shippingReplenishmentRepository = _shippingReplenishmentRepository;
            this._receivingOrderDetailRepository = _receivingOrderDetailRepository;
            this._pickingOrderDetailRepository = _pickingOrderDetailRepository;
            this._shippingLockCellRepository = _shippingLockCellRepository;
            this._putawayOrderRepository = _putawayOrderRepository;
            this._inventoryLogRepository = _inventoryLogRepository;
            this._pickingOrderRepository = _pickingOrderRepository;
            this._inventoryRepository = _inventoryRepository;
            this._instructRepository = _instructRepository;
            this._cellRepository = _cellRepository;
            this._wcsHttpClient = _wcsHttpClient;
            this._unitOfWork = _unitOfWork;
        }

        public bool FinishReplenishment(string pickcode, out string message)
        {
            message = string.Empty;
            var pickobj = _pickingOrderRepository.QueryEntityWhere(x => x.Code == pickcode && x.SourceType == 2 && x.Status == 4);
            if (pickobj == null)
            {
                message = "找不到下架单！";
                return false;
            }
            var instructobj = _instructRepository.QueryEntityWhere(x => x.PalletBarcode == pickobj.PalletBarcode && x.Status == 2 && x.InstructType == 11);
            if (instructobj == null)
            {
                message = "未查询到指令！";
                return false;
            }
            _unitOfWork.BeginTransaction();
            instructobj.Status = 4;
            instructobj.EndTime = DateTime.Now;
            if (instructobj.RelatedOrderId == null)
            {
                message = "找不到关联的出库单信息！";
                return false;
            }
            var sobj = _shippingReplenishmentRepository.QueryEntityById((long)instructobj.RelatedOrderId);
            if (sobj == null)
            {
                message = "找不到关联的补货单信息！";
                return false;
            }
            sobj.Status = 4;
            sobj.ModifyDate = DateTime.Now;
            //出库单单子明细
            var sllist = _shippingLockCellRepository.GetEntityWhereAll(x => x.InventoryId == sobj.ToInventoryId && x.Status != 4);
            foreach (var item2 in sllist)
            {
                item2.InventoryQty += sobj.AddQty;
            }
            if (sobj.FromInventoryId == null)
            {
                message = "找不到原始的库存信息！";
                return false;
            }
            Inventory? FrominventoryModel = _inventoryRepository.QueryEntityById((long)sobj.FromInventoryId);
            if (FrominventoryModel == null)
            {
                message = "未查询到库存信息！";
                _unitOfWork.RollbackChanges();
                return false;
            }
            FrominventoryModel.AvailableQty -= instructobj.Qty;
            FrominventoryModel.PickedQty += instructobj.Qty;
            if (FrominventoryModel.AvailableQty == 0)
            {
                _inventoryRepository.DelEntity(FrominventoryModel);
                if (FrominventoryModel.LocationId == null)
                {
                    message = "找不到原始仓位的信息！";
                    _unitOfWork.RollbackChanges();
                    return false;
                }
                var frominventorycell = _inventoryRepository.QueryEntityWhere(x => x.LocationId == FrominventoryModel.LocationId && x.Id != FrominventoryModel.Id);
                if (frominventorycell == null)
                {
                    var fromcellobj = _cellRepository.QueryEntityById((long)FrominventoryModel.LocationId);
                    if (fromcellobj != null)
                    {
                        fromcellobj.IsLock = false;
                        fromcellobj.FullStatus = 0;
                        fromcellobj.BusinessType = 0;
                    }
                }
            }
            else
            {
                FrominventoryModel.AllocateQty = 0;
                FrominventoryModel.IsLock = false;
                FrominventoryModel.Status = 1;
            }
            if (sobj.ToInventoryId == null)
            {
                message = "找不到目标库存信息！";
                return false;
            }
            Inventory? ToinventoryModel = _inventoryRepository.QueryEntityById((long)sobj.ToInventoryId);
            if (ToinventoryModel == null)
            {
                message = "未查询到库存信息！";
                _unitOfWork.RollbackChanges();
                return false;
            }
            ToinventoryModel.AvailableQty += instructobj.Qty;
            ToinventoryModel.IsLock = false;
            var FrominventoryLog = new InventoryLog
            {
                Id = YitIdHelper.NextId(),
                SourceType = 1,
                SourceSn = sobj.BillType == 2?"----------":sobj.OrdeSn,
                WarehouseId = FrominventoryModel.WarehouseId,
                WarehouseName = FrominventoryModel.WarehouseName,
                AreaName = FrominventoryModel.AreaName,
                LocationCode = FrominventoryModel.LocationCode,
                PalletBarcode = FrominventoryModel.PalletBarcode,
                MaterialId = FrominventoryModel.MaterialId,
                MaterialCode = FrominventoryModel.MaterialCode,
                MaterialName = FrominventoryModel.MaterialName,
                BatchNo = FrominventoryModel.BatchNo,
                StartQty = FrominventoryModel.AvailableQty + instructobj.Qty,
                ChangeQty = -instructobj.Qty,
                EndQty = FrominventoryModel.AvailableQty,
                BaseUnitId = FrominventoryModel.UnitId,
                BaseUnitName = FrominventoryModel.UnitName,
                CreateDate = DateTime.Now,
                Remark = sobj.BillType == 2 ? "主动补货":"被动补货"
            };
            _inventoryLogRepository.AddEntity(FrominventoryLog);
            if(ToinventoryModel.RelatedOrderDetailId==null)
            {
                message = "关联的入库单id有误！";
                return false;
            }
            var reobj = _receivingOrderDetailRepository.QueryEntityById((long)ToinventoryModel.RelatedOrderDetailId);
            var ToinventoryLog = new InventoryLog
            {
                Id = YitIdHelper.NextId(),
                SourceType = 0,
                SourceSn = reobj!=null? reobj.OrderSn:"无编号",
                WarehouseId = ToinventoryModel.WarehouseId,
                WarehouseName = ToinventoryModel.WarehouseName,
                AreaName = ToinventoryModel.AreaName,
                LocationCode = ToinventoryModel.LocationCode,
                PalletBarcode = ToinventoryModel.PalletBarcode,
                MaterialId = ToinventoryModel.MaterialId,
                MaterialCode = ToinventoryModel.MaterialCode,
                MaterialName = ToinventoryModel.MaterialName,
                BatchNo = ToinventoryModel.BatchNo,
                StartQty = ToinventoryModel.AvailableQty - instructobj.Qty,
                ChangeQty = instructobj.Qty,
                EndQty = ToinventoryModel.AvailableQty,
                BaseUnitId = ToinventoryModel.UnitId,
                BaseUnitName = ToinventoryModel.UnitName,
                CreateDate = DateTime.Now,
                Remark = sobj.BillType == 2 ? "主动补货" : "被动补货"
            };
            _inventoryLogRepository.AddEntity(ToinventoryLog);
            var picklist = _pickingOrderRepository.GetEntityWhereAll(x => x.SourceType == 2 && x.Status == 4 && x.PalletBarcode == pickobj.PalletBarcode);
            foreach (var item in picklist)
            {
                item.Status = 5;
                item.ModifyDate = DateTime.Now;
                _pickingOrderRepository.UpdEntity(item);
            }
            Instruct instruct2 = new Instruct
            {
                Status = 2,
                WarehouseCode = ToinventoryModel.WarehouseCode,
                ToLocation = ToinventoryModel.LocationCode,
                WorkDeviceType = 1,
                InstructType = 7,
                Action = 0,
                RelatedOrderId = ToinventoryModel.RelatedOrderDetailId,
                ExpectedToLocation = ToinventoryModel.LocationCode,
                InstructIndex = 1,
                PalletBarcode = ToinventoryModel.PalletBarcode,
                Priority = 9999,
                Qty = (decimal)ToinventoryModel.AvailableQty,
                BusinessType = (int)EmBusinessType.In,
            };
            _instructRepository.AddEntity(instruct2);
            string str = DateTime.Now.ToString("yyyyMMddHHmmssfff");
            string putawayCode = "SRT" + str;
            PutawayOrder putawayOrder = new PutawayOrder();
            putawayOrder.Id = YitIdHelper.NextId();
            putawayOrder.Code = putawayCode;
            putawayOrder.BillType = 2;
            putawayOrder.RelatedOrderDetailId = ToinventoryModel.RelatedOrderDetailId;
            putawayOrder.PalletBarcode = ToinventoryModel.PalletBarcode;
            putawayOrder.LocationCode = ToinventoryModel.LocationCode;
            putawayOrder.LocationDepth = ToinventoryModel.LocationDepth == 0 ? null : ToinventoryModel.LocationDepth;
            putawayOrder.Status = 4;
            putawayOrder.Qty = ToinventoryModel.AvailableQty;
            putawayOrder.MaterialId = ToinventoryModel.MaterialId;
            putawayOrder.MaterialCode = ToinventoryModel.MaterialCode;
            putawayOrder.MaterialName = ToinventoryModel.MaterialName;
            putawayOrder.MaterialKeyId = ToinventoryModel.MaterialKeyId;
            putawayOrder.SourceType = 1;
            putawayOrder.CreateDate = DateTime.Now;
            putawayOrder.Roadway = ToinventoryModel.RoutewayId.ToString();
            _putawayOrderRepository.AddEntity(putawayOrder);
 
            if (_unitOfWork.SaveChangesEntity())
            {
                try
                {
                    string winFormsAppPath = @"D:\桌面\PrintBQ\帅佳\帅佳\bin\Debug\net6.0-windows\帅佳.exe";

                    // 你要传递给WinForms应用的参数  
                    string parameter = $"补,托盘：{putawayOrder.PalletBarcode},{sobj.Remark}";

                    // 使用Process.Start启动WinForms应用并传递参数  
                    Process.Start(winFormsAppPath, parameter);
                }
                catch (Exception ex)
                {
                    message = "操作成功了，但打印异常！" + ex.Message;
                }             
                _unitOfWork.CommitChanges();
                return true;
            }
            _unitOfWork.RollbackChanges();
            return false;
        }

        public List<ShippingReplenishment> GetShippingReplenishmentList(string? ordersn, int status, int pageIndex, int pageSize, out int totalCount)
        {
            var list = _shippingReplenishmentRepository.GetEntityAlls();

            if (!string.IsNullOrEmpty(ordersn))
                list = list.Where(x => x.OrdeSn.Contains(ordersn));
            if (status < 8)
                list = list.Where(x => x.Status == status);

            totalCount = list.Count();
            var lists = _shippingReplenishmentRepository.GetEntityAlls(list, pageIndex, pageSize, out totalCount, x => x.CreateDate, false);
            return lists.ToList();
        }

        public bool StartReplenishment(ReplenishmentDto m, out string message)
        {
            message = string.Empty;
            bool result = false;
            var ilist = _inventoryRepository.GetEntityAlls();
            try
            {
                _unitOfWork.BeginTransaction();
                Dictionary<string, int> skeyValuePairs = new Dictionary<string, int>();
                var sobj = _shippingReplenishmentRepository.QueryEntityById(m.Id);
                if (sobj == null)
                {
                    message = "找不到补货单！";
                    return false;
                }
                if (sobj.Status != 0)
                {
                    message = "作业中或已完成的单据无法操作！";
                    return false;
                }
                sobj.Status = 3;
                #region 呼叫库存中的托盘
                Inventory? inventoryModel = ilist.FirstOrDefault(x => x.Id == m.InventoryId);
                //状态修改出库在途         
                if (inventoryModel == null)
                {
                    message = "获取库存信息失败！";
                    return false;
                }
                #region 如果浅深位有货物产生移库操作
                if (inventoryModel.AreaCode.Contains('L'))
                {
                    //排
                    string rows = inventoryModel.LocationCode.Substring(7, 1);
                    if (string.IsNullOrEmpty(rows))
                    {
                        message = "获取仓位排失败！";
                        return false;
                    }
                    if (rows == "1")
                    {
                        string[] parts = inventoryModel.LocationCode.Substring(5).Split(separator: '_');
                        int rou = Convert.ToInt32(parts[0]); // 巷道是第一个数字
                        int row = Convert.ToInt32(parts[1]);    // 排是第二个数字
                        int col = Convert.ToInt32(parts[2]);    // 列是第三个数字
                        int lev = Convert.ToInt32(parts[3]);  // 层是第
                        string modifiedcellcode = $"Cell:{rou}_2_{col}_{lev}_1";
                        var inventorycell = _inventoryRepository.QueryEntityWhere(x => x.LocationCode == modifiedcellcode);
                        if (inventorycell != null)
                        {
                            message = $"浅货位 {modifiedcellcode} 已有物资，请先移走在进行操作！";
                            return false;
                        }
                    }
                    else if (rows == "4")
                    {
                        string[] parts = inventoryModel.LocationCode.Substring(5).Split(separator: '_');
                        int rou = Convert.ToInt32(parts[0]); // 巷道是第一个数字
                        int row = Convert.ToInt32(parts[1]);    // 排是第二个数字
                        int col = Convert.ToInt32(parts[2]);    // 列是第三个数字
                        int lev = Convert.ToInt32(parts[3]);  // 层是第
                        string modifiedcellcode = $"Cell:{rou}_3_{col}_{lev}_1";
                        var inventorycell = _inventoryRepository.QueryEntityWhere(x => x.LocationCode == modifiedcellcode);
                        if (inventorycell != null)
                        {
                            message = $"浅货位 {modifiedcellcode} 已有物资，请先移走在进行操作！";
                            return false;
                        }
                    }
                }
                #endregion
                var inventorylist = ilist.Where(x => x.PalletBarcode == m.PallteCode && (x.Status == 1 || x.Status == 5));
                if (inventorylist.Any())
                {
                    foreach (var item2 in inventorylist)
                    {
                        item2.IsLock = true;
                        item2.Status = 4;
                        _inventoryRepository.UpdEntity(item2);
                    }
                }
                var cellobj = _cellRepository.QueryEntityWhere(x => x.Code == inventoryModel.LocationCode);
                if (cellobj == null)
                {
                    message = "未查询到仓位" + inventoryModel.LocationCode;
                }

                #region 添加指令
                Instruct inobj = new Instruct();
                inobj.WarehouseCode = inventoryModel.WarehouseCode;
                inobj.Status = 2;
                inobj.ToLocation = inventoryModel.LocationCode;
                inobj.WorkDeviceType = 1;
                inobj.InstructType = 11;
                inobj.Action = 0;
                inobj.RelatedOrderId = sobj.Id;
                inobj.RelatedOrderDetailId = 0;
                inobj.ExpectedToLocation = inventoryModel.LocationCode;
                inobj.InstructIndex = 1;
                inobj.PalletBarcode = m.PallteCode;
                inobj.ScanedBarcode = m.PallteCode;
                inobj.Priority = 9999;
                inobj.Qty = (decimal)sobj.AddQty;
                inobj.BusinessType = (int)EmBusinessType.ReplenishmentDown;
                _instructRepository.AddEntity(inobj);
                #endregion
                #region 添加下架单
                string strr = DateTime.Now.ToString("yyyyMMddHHmmssfff");
                string pickCode = "REP" + strr;
                PickingOrder pickOrder = new PickingOrder();
                pickOrder.Id = YitIdHelper.NextId();
                pickOrder.Code = pickCode;
                pickOrder.WarehouseCode = inventoryModel.WarehouseCode;
                pickOrder.WarehouseName = inventoryModel.WarehouseName;
                pickOrder.BillType = 2;
                pickOrder.PalletBarcode = m.PallteCode;
                pickOrder.Roadway = cellobj.RoutewayId.ToString();
                pickOrder.LocationCode = cellobj.Code;
                pickOrder.LocationDepth = cellobj.DepthIndex;
                pickOrder.Status = 4;
                pickOrder.Qty = sobj.AddQty;
                pickOrder.MaterialId = inventoryModel.MaterialId;
                pickOrder.MaterialCode = inventoryModel.MaterialCode;
                pickOrder.MaterialName = inventoryModel.MaterialName;
                pickOrder.MaterialKeyId = inventoryModel.MaterialKeyId;
                pickOrder.BatchNo = inventoryModel.BatchNo;
                pickOrder.SourceType = 2;
                pickOrder.RelatedOrderDetailId = sobj.Id;
                pickOrder.CreateDate = DateTime.Now;
                if (!skeyValuePairs.ContainsKey(m.PallteCode))
                    skeyValuePairs.Add(m.PallteCode, 1);
                _pickingOrderRepository.AddEntity(pickOrder);
                PickingOrderDetail pickOrderDetail = new PickingOrderDetail();
                pickOrderDetail.Id = YitIdHelper.NextId();
                pickOrderDetail.OrderId = pickOrder.Id;
                pickOrderDetail.PalletBarcode = m.PallteCode;
                pickOrderDetail.MaterialBarcode = inventoryModel.MaterialCode;
                _pickingOrderDetailRepository.AddEntity(pickOrderDetail);
                #endregion
                #endregion
                //库存中已有物料增加数量
                if (m.Qty <= 0 || m.Qty == null)
                {
                    message = "数量有误！";
                    result = true;
                }
                result = _unitOfWork.SaveChangesEntity();
                if (result)
                {
                    if (Config.IsDev == false)
                    {
                        var picklist = _pickingOrderRepository.GetEntityWhereAll(x => x.Status == 4 && x.SourceType == 2);
                        foreach (var item in skeyValuePairs)
                        {
                            var pickobj = picklist.FirstOrDefault(x => x.PalletBarcode == item.Key);
                            if (pickobj == null)
                                continue;
                            WcsTaskDto wcsTaskDto = new WcsTaskDto
                            {
                                TaskCode = pickobj.Code,
                                TaskType = 2,
                                StartPoint = pickobj.LocationCode
                            };
                            var wcsresult = _wcsHttpClient.OutTaskApi(wcsTaskDto);
                            if (wcsresult.ReturnStatus == 1)
                            {
                                message = wcsresult.ReturnInfo;
                                _unitOfWork.RollbackChanges();
                                return false;
                            }
                        }
                    }
                    message = "操作成功！";
                    _unitOfWork.CommitChanges();
                    return true;
                }
                _unitOfWork.RollbackChanges();
                return false;
            }
            catch (Exception)
            {
                _unitOfWork.RollbackChanges();
                throw;
            }
        }
    }
}
